"""设备列表组件。"""

from __future__ import annotations

from PySide6.QtCore import Qt, Signal
from PySide6.QtGui import QKeyEvent
from PySide6.QtWidgets import (
    QApplication,
    QCheckBox,
    QHeaderView,
    QHBoxLayout,
    QPushButton,
    QTableWidget,
    QTableWidgetItem,
    QWidget,
)

from src.core.models import Device


class CheckboxHeader(QHeaderView):
    """自定义表头，在第一列添加全选复选框。"""

    def __init__(self, parent=None) -> None:
        super().__init__(Qt.Orientation.Horizontal, parent)
        self._select_all_checkbox = QCheckBox(self)
        self._select_all_checkbox.setToolTip("全选/取消全选")
        self._select_all_checkbox.stateChanged.connect(self._on_select_all_changed)
        self._updating_checkbox = False  # 防止循环更新
        # 监听列宽变化，更新复选框位置
        self.sectionResized.connect(self._update_checkbox_position)
        
    def _on_select_all_changed(self, state: int) -> None:
        """全选复选框状态变化时的处理。"""
        if self._updating_checkbox:
            return
        # 获取父表格控件
        table = self.parent()
        if isinstance(table, QTableWidget):
            # 通知表格全选状态变化（Checked状态值为2）
            checked = state == Qt.CheckState.Checked.value
            table._on_header_select_all_changed(checked)  # type: ignore[attr-defined]
    
    def set_select_all_state(self, checked: bool, partial: bool = False) -> None:
        """设置全选复选框的状态。"""
        self._updating_checkbox = True
        if partial:
            # 部分选中状态（三态复选框）
            self._select_all_checkbox.setTristate(True)
            self._select_all_checkbox.setCheckState(Qt.CheckState.PartiallyChecked)
        else:
            self._select_all_checkbox.setTristate(False)
            self._select_all_checkbox.setChecked(checked)
        self._updating_checkbox = False
    
    def _update_checkbox_position(self) -> None:
        """更新全选复选框的位置。"""
        if self.count() > 0:
            # 获取第一列的宽度
            section_width = self.sectionSize(0)
            # 计算复选框的位置（居中）
            checkbox_size = 18  # 复选框大小
            x = (section_width - checkbox_size) // 2
            y = (self.height() - checkbox_size) // 2
            self._select_all_checkbox.setGeometry(x, y, checkbox_size, checkbox_size)
    
    def resizeEvent(self, event) -> None:  # type: ignore[override]
        """重写resize事件，调整全选复选框的位置。"""
        super().resizeEvent(event)
        self._update_checkbox_position()
    
    def showEvent(self, event) -> None:  # type: ignore[override]
        """显示事件，确保复选框可见。"""
        super().showEvent(event)
        self._select_all_checkbox.show()
        self._update_checkbox_position()


class DeviceTable(QTableWidget):
    """右侧设备列表，支持双击打开详情。"""

    device_activated = Signal(object)
    detail_requested = Signal(object)  # 查看详情信号

    def __init__(self, parent=None) -> None:
        super().__init__(0, 6, parent)  # 6列：复选框、设备名称、描述、Product Key、设备 SN、操作
        self._checkbox_column = 0
        self._detail_column = 5

        self.setHorizontalHeaderLabels(["", "设备名称", "描述", "Product Key", "设备 SN", "操作"])
        self.setSelectionBehavior(QTableWidget.SelectionBehavior.SelectRows)
        self.setSelectionMode(QTableWidget.SelectionMode.SingleSelection)
        self.cellDoubleClicked.connect(self._on_double_click)
        self._device_ids: list[int] = []
        self._devices: dict[int, Device] = {}
        self._checkboxes: dict[int, QCheckBox] = {}  # 存储每个设备ID对应的复选框
        self.verticalHeader().setVisible(False)
        self.verticalHeader().setDefaultSectionSize(int(self.verticalHeader().defaultSectionSize() * 1.0))
        self.setAlternatingRowColors(True)
        self.setWordWrap(False)
        self.setEditTriggers(QTableWidget.EditTrigger.NoEditTriggers)
        self._configure_header()
        self._apply_styles()

    def set_devices(self, devices: list[Device]) -> None:
        self.setRowCount(len(devices))
        self._device_ids = []
        self._devices = {}
        self._checkboxes = {}

        for row, device in enumerate(devices):
            self._device_ids.append(device.id)
            self._devices[device.id] = device
            self._set_row(row, device)

        self._adjust_column_widths()
        # 更新全选复选框状态
        self._update_select_all_checkbox_state()

    def get_device(self, device_id: int) -> Device | None:
        return self._devices.get(device_id)

    def current_device(self) -> Device | None:
        row = self.currentRow()
        if row < 0 or row >= len(self._device_ids):
            return None
        return self._devices.get(self._device_ids[row])

    def get_selected_device_ids(self) -> list[int]:
        """获取所有勾选的设备ID列表。"""
        selected_ids = []
        for device_id, checkbox in self._checkboxes.items():
            if checkbox.isChecked():
                selected_ids.append(device_id)
        return selected_ids

    def _set_row(self, row: int, device: Device) -> None:
        # 第一列：复选框（居中对齐）
        checkbox = QCheckBox()
        self._checkboxes[device.id] = checkbox
        # 监听复选框状态变化，更新全选复选框状态
        checkbox.stateChanged.connect(self._on_device_checkbox_changed)
        # 创建容器widget实现居中对齐
        checkbox_container = QWidget()
        checkbox_layout = QHBoxLayout(checkbox_container)
        checkbox_layout.setContentsMargins(0, 0, 0, 0)
        checkbox_layout.addStretch()  # 左侧弹性空间
        checkbox_layout.addWidget(checkbox)
        checkbox_layout.addStretch()  # 右侧弹性空间，实现居中对齐
        self.setCellWidget(row, self._checkbox_column, checkbox_container)

        # 其他列：设备信息（居中对齐）
        values = [
            device.nickname,
            device.type_node_name,
            device.product_key,
            device.device_sn,
        ]
        for col, value in enumerate(values, start=1):  # 从第1列开始（第0列是复选框）
            item = QTableWidgetItem(value)
            item.setTextAlignment(Qt.AlignmentFlag.AlignCenter | Qt.AlignmentFlag.AlignVCenter)  # 设置居中对齐
            self.setItem(row, col, item)

        # 最后一列：查看详情按钮
        button = QPushButton("查看详情", self)
        button.setMinimumHeight(28)
        button.clicked.connect(lambda _=False, device_id=device.id: self.detail_requested.emit(device_id))
        self.setCellWidget(row, self._detail_column, button)

    def _on_double_click(self, row: int, column: int) -> None:  # noqa: ARG002
        """双击设备行时，切换复选框状态。"""
        if 0 <= row < len(self._device_ids):
            device_id = self._device_ids[row]
            # 获取该设备对应的复选框
            checkbox = self._checkboxes.get(device_id)
            if checkbox:
                # 切换复选框状态
                checkbox.setChecked(not checkbox.isChecked())

    def _configure_header(self) -> None:
        # 使用自定义表头，支持全选复选框
        header = CheckboxHeader(self)
        self.setHorizontalHeader(header)
        # 先设置复选框列为固定宽度，必须在设置其他模式之前
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.Fixed)
        header.resizeSection(0, 30)  # 立即设置复选框列宽度为30px
        
        # 逐个设置其他列为Interactive模式（不能使用全局设置，否则会覆盖复选框列的固定模式）
        for col in range(1, self.columnCount()):
            header.setSectionResizeMode(col, QHeaderView.ResizeMode.Interactive)
        
        header.setDefaultSectionSize(180)
        # 设置其他列的最小列宽（复选框列已单独设置为固定模式，不受此影响，适配1080p）
        header.setMinimumSectionSize(120)

    def _adjust_column_widths(self) -> None:
        """调整列宽，确保复选框列始终保持25px宽度。"""
        header = self.horizontalHeader()
        
        # 强制设置复选框列为固定模式并设置宽度（必须在设置其他列之前）
        header.setSectionResizeMode(0, QHeaderView.ResizeMode.Fixed)
        header.resizeSection(0, 30)  # 复选框列宽度设置为30px
        
        # 设置其他列的宽度（适配1080p屏幕）
        widths = [30, 180, 160, 160, 160, 100]  # 复选框列宽度设置为30px
        for index, width in enumerate(widths):
            if index != 0:  # 跳过复选框列（已单独设置为固定模式）
                # 确保其他列不是固定模式
                if header.sectionResizeMode(index) == QHeaderView.ResizeMode.Fixed:
                    header.setSectionResizeMode(index, QHeaderView.ResizeMode.Interactive)
                header.resizeSection(index, width)

    def _apply_styles(self) -> None:
        """统一设备列表选中与悬停时的配色，保持与分类树一致。"""
        self.setStyleSheet(
            """
            QTableWidget::item:selected {
                background-color: #dbe8ff;
                color: #0b2f5b;
            }
            QTableWidget::item:selected:active {
                background-color: #c8dcff;
                color: #0b2f5b;
            }
            QTableWidget::item:hover {
                background-color: #eef4ff;
            }
            """
        )

    def keyPressEvent(self, event: QKeyEvent) -> None:
        """处理键盘事件，支持Ctrl+C复制选中单元格内容。"""
        # 检查是否按下了Ctrl+C
        if event.key() == Qt.Key.Key_C and event.modifiers() == Qt.KeyboardModifier.ControlModifier:
            self._copy_selected_cells()
            event.accept()
        else:
            super().keyPressEvent(event)

    def _copy_selected_cells(self) -> None:
        """复制选中的单元格内容到剪贴板。"""
        selected_items = self.selectedItems()
        if not selected_items:
            return

        # 获取剪贴板
        clipboard = QApplication.clipboard()

        # 过滤掉复选框列和操作列（第0列和第5列）
        valid_items = [
            item for item in selected_items
            if item and item.column() != self._checkbox_column and item.column() != self._detail_column
        ]

        if not valid_items:
            return

        # 如果只选中了一个有效单元格，直接复制该单元格的内容
        if len(valid_items) == 1:
            text = valid_items[0].text()
            clipboard.setText(text)
            return

        # 如果选中了多个单元格，按行和列的顺序组织数据
        # 获取所有选中单元格的行和列
        rows = sorted(set(item.row() for item in valid_items))
        cols = sorted(set(item.column() for item in valid_items))

        # 构建复制文本（使用制表符分隔列，换行符分隔行）
        text_lines = []
        for row in rows:
            row_data = []
            for col in cols:
                # 跳过复选框列和操作列
                if col == self._checkbox_column or col == self._detail_column:
                    continue
                item = self.item(row, col)
                if item:
                    row_data.append(item.text())
            if row_data:  # 只添加非空行
                text_lines.append("\t".join(row_data))

        if text_lines:
            clipboard.setText("\n".join(text_lines))
    
    def _on_header_select_all_changed(self, checked: bool) -> None:
        """表头全选复选框状态变化时的处理。"""
        # 批量更新所有设备的复选框状态
        # 临时断开信号连接，避免多次触发状态更新
        for checkbox in self._checkboxes.values():
            checkbox.blockSignals(True)
            checkbox.setChecked(checked)
            checkbox.blockSignals(False)
        # 更新全选复选框状态（避免循环更新）
        self._update_select_all_checkbox_state()
    
    def _on_device_checkbox_changed(self) -> None:
        """设备复选框状态变化时的处理，更新全选复选框状态。"""
        self._update_select_all_checkbox_state()
    
    def _update_select_all_checkbox_state(self) -> None:
        """根据当前设备复选框的状态，更新全选复选框的状态。"""
        header = self.horizontalHeader()
        if not isinstance(header, CheckboxHeader):
            return
        
        if not self._checkboxes:
            # 没有设备时，全选复选框未选中
            header.set_select_all_state(False)
            return
        
        checked_count = sum(1 for checkbox in self._checkboxes.values() if checkbox.isChecked())
        total_count = len(self._checkboxes)
        
        if checked_count == 0:
            # 全部未选中
            header.set_select_all_state(False)
        elif checked_count == total_count:
            # 全部选中
            header.set_select_all_state(True)
        else:
            # 部分选中（三态）
            header.set_select_all_state(False, partial=True)


